#include "Config.h"
#include "reg.h"
#include "typedefs.h"
#include "Printf.h"
#include "I2C.h"
#include "CPU.h"
#include "Global.h"
#include "TouchScreen.h"

#define DEF_X (0)
#define DEF_Y (0)

static TSPOINT CurPoint={0,0};
static BYTE CurState=TOUCH_CLOSED;

//Adjust TSC
S8 Xslope=0, Yslope=0;
LONG Xoff=0, Yoff=0;
WORD Xres=0, Yres=0;

BYTE GetZPS(void);
WORD GetXPS(void);
WORD GetYPS(void);
BYTE GetPS(TSPOINT *point);
BYTE ReadScrPt(TSPOINT *point);

void InitTSC(void)
{
//	INTEDGE   |= 0x04;	//Level triggered
	INTPOL	  |= 0x04;	//High Level / Rising Edge
//	INTPRIORITY |= 0x04;
	INTENABLE |= 0x04;	//INT9 enabled

	WriteTW88(0xff, MCU_PAGE);
	WriteTW88(0x20, (ReadTW88(0x20) | 0x04));	  // enable code cache

	WriteTW88( 0xff, REMO_PAGE );
	WriteTW88( 0x10, 0x00 ); 
	WriteTW88( 0x11, 0xc0 );				// div 2, rsel=10k, 
	WriteTW88( 0x14, 0x08 );				// div 2, rsel=10k, 
	CurPoint.x = DEF_X;
	CurPoint.y = DEF_Y;
	CurState = TOUCH_IDLE;
	Xslope = DEF_XSLOPE;
	Yslope = DEF_YSLOPE;
	Xoff = DEF_XOFF;
	Yoff = DEF_YOFF;
	Xres = DEF_XRES;
	Yres = DEF_YRES;
	//Printf("\r\n SLOF %bd %bd %ld %ld", Xslope, Yslope, Xoff, Yoff);
}

extern XDATA BYTE touch_flag;

BYTE IntTouch(void)
{
	switch (CurState)
	{
		case TOUCH_POPUP:
		case TOUCH_IDLE:
			if (touch_flag == 1)
			{
				CurState = TOUCH_PRESS;
			}
			else
			{
				CurState = TOUCH_IDLE;

				return 0;
			}
			break;
		
		case TOUCH_PRESS:
		case TOUCH_HOLD:
			break;
		
		case TOUCH_CLOSED:
		default:
			touch_flag = 0;
			return 0;
			break;		
	}

	touch_flag = 0;

	return 1;
}

void GetTouchInfo(TSPOINT *Point, BYTE *State)
{
	switch (CurState)
	{
		case TOUCH_POPUP:
		case TOUCH_IDLE:
			Point->x = DEF_X;
			Point->y = DEF_Y;
			*State = TOUCH_IDLE;
			break;
		
		case TOUCH_PRESS:
			if (ReadScrPt(Point) == 1)
			{
				*State = TOUCH_PRESS;
				CurState = TOUCH_HOLD;
			}
			else
			{
				*State = TOUCH_IDLE;
				CurState = TOUCH_IDLE;
			}
			CurPoint.x = Point->x;
			CurPoint.y = Point->y;
			//Printf("\r\n TSC x|y %d|%d %bd", Point->x, Point->y, *State);
			break;
			
		case TOUCH_HOLD:
			if (ReadScrPt(Point) == 1)
			{
				*State = TOUCH_HOLD;
				CurState = TOUCH_HOLD;
			}
			else
			{
				*State = TOUCH_POPUP;
				CurState = TOUCH_POPUP;
			}
			CurPoint.x = Point->x;
			CurPoint.y = Point->y;
			//Printf("\r\n TSC x|y %d|%d %bd", Point->x, Point->y, *State);
			break;
		
		case TOUCH_CLOSED:
		default:
			break;
	}

	return;
}

BYTE ReadScrPt(TSPOINT *point)
{
	DWORD temp;
	BYTE j;
	TSPOINT ptmin, ptmax, pt;

	//Pre
	if ((GetPS(point)) == 0)
	{
		point->x = DEF_X;
		point->y = DEF_Y;

		return 0;
	}
/*
	//Alcu
	ptmin.x = point->x;
	ptmin.y = point->y;
	ptmax.x = point->x;
	ptmax.y = point->y;
	pt.x = point->x;
	pt.y = point->y;
	for ( j=0; j<5; j++ ) {
		if((GetPS(point)) == 0){
			point->x = DEF_X;
			point->y = DEF_Y;
			return 0;
		}

		pt.x += point->x;
		pt.y += point->y;
		
		if ( point->x < ptmin.x ) ptmin.x = point->x;
		else if ( point->x > ptmax.x ) ptmax.x = point->x;

		if ( point->y < ptmin.y ) ptmin.y = point->y;
		else if ( point->y > ptmax.y ) ptmax.y = point->y;
	}
	
	pt.x -= ptmin.x;
	pt.y -= ptmin.y;
	pt.x -= ptmax.x;
	pt.y -= ptmax.y;

	point->x = pt.x >> 2;   // divide by 4
	point->y = pt.y >> 2;   // divide by 4

	//Printf("\r\n ReadScrPt x|y %d|%d\r\n", point->x, point->y);
	//Printf("\r\nTest5\r\n");

	point->x = ADC2SCR(point->x, Xslope, Xoff);
	point->y = ADC2SCR(point->y, Yslope, Yoff);
	if((((S16)(point->x))<0)||(((S16)(point->x))>Xres)||(((S16)(point->y))<0)||(((S16)(point->y))>Yres)){
		point->x=DEF_X;
		point->y=DEF_Y;
		return 0;	
	}
*/

	temp = point->x * 15;
	point->x = (WORD)(temp / 64);
	temp = point->y * 17;
	point->y = (WORD)(temp / 128);

//	Printf("x = %x | y = %x\n", point->x, point->y);

	return 1;	
}

void CalSlopeOff(U16 adc0, U16 adc1, U16 scr0, U16 scr1, S8* slope, LONG* off)
{
	*off = (LONG)adc1-(LONG)adc0;
	*off *= 10;
	*off /= (LONG)scr1-(LONG)scr0;
	*slope = (S8)(*off);
	
	*off *= 0 - (LONG)scr0;
	*off += ((LONG)adc0)*10;

	return;
}

U16 ADC2SCR(U16 adc, S8 slope, LONG off)
{
	LONG temp;

	off *= -1;
	off += ((LONG)adc)*10;
	off /= slope;
	adc = (WORD)off;

	return adc;	
}

U8 Calculate_8BitsChecksum(U8 *msg, S32 s32Length)
{
	S32 s32Checksum = 0;
	S32 i;

	for (i = 0; i < s32Length; i++)
	{
		s32Checksum += msg[i];
	}

	return (U8)((-s32Checksum) & 0xFF);
}

BYTE GetPS(TSPOINT *point)
{
/*	
	WriteTW88( 0xff, REMO_PAGE );

	point->x = (WORD)GetZPS();
	//Printf("\r\npoint->x=%d\r\n",point->x);
	if(point->x <= 220){
		//Printf("\rTest1\r\n");
		//EVB
		#ifdef TW8823EVB
		point->x = GetXPS();
		point->y = GetYPS();
		#endif
		//SH-DEMO
		#ifdef TW8823SHDEMO
		point->x = GetYPS();
		point->y = GetXPS();
		#endif
	}else{
		point->x = DEF_X;
		point->y = DEF_Y;
		return 0;
	}
	
	//WriteTW88( 0x10, 0x21 );				// write Start, erase Ready, mode Z1 for touch
	return 1;
*/

	BYTE Buf[8];
	TSPOINT pt2;

	MDrv_SW_IIC_ReadBytes(0x60<<1, Buf, 8);
//	Printf("%02bx %02bx %02bx %02bx %02bx %02bx %02bx", Buf[0], Buf[1], Buf[2], Buf[3], Buf[4], Buf[5], Buf[6], Buf[7]);

	if (Buf[7] == Calculate_8BitsChecksum(Buf, 7))
	{
		if ((Buf[0] == 0))
		{
			Printf(" [release]\n");

			return 0;
		}
		else
		{
			point->x = ((Buf[1]&0xF0)<<4) | Buf[2];
			point->y = ((Buf[1]&0x0F)<<8) | Buf[3];

			pt2.x = ((Buf[4]&0xF0)<<4) | Buf[5];
			pt2.y = ((Buf[4]&0x0F)<<8) | Buf[6];

			Printf(" [x1=%x y1=%x x2=%x y2=%x]\n", point->x, point->y, pt2.x, pt2.y);

			return 1;
		}
	}
	else
	{
		Printf(" [checksum error]\n");
		return 0;
	}

}

WORD GetXPS(void)
{
	WORD v;
	WriteTW88( 0x10, 0x08 );			// write Start, erase Ready, mode XPOS
	WriteTW88( 0x10, 0x20 );			// adc start with mode XPOS
	while (( ReadTW88( 0x10 ) & 8 ) != 8 ) ;  			// wait until ADC
	WriteTW88( 0x10, 0x08 );			// write Start, erase Ready, mode XPOS
	WriteTW88( 0x10, 0x20 );			// adc start with mode XPOS
	while (( ReadTW88( 0x10 ) & 8 ) != 8 ) ;  			// wait until ADC
	WriteTW88( 0x10, 0x08 );			// write Start, erase Ready, mode XPOS
	WriteTW88( 0x10, 0x20 );			// adc start with mode XPOS
	while (( ReadTW88( 0x10 ) & 8 ) != 8 ) ;  			// wait until ADC

	v = ReadTW88( 0x12 );
	v <<= 4;
	v += ReadTW88( 0x13 );

	return v;
}

WORD GetYPS(void)
{
	WORD v;
	WriteTW88( 0x10, 0x0b );			// adc start with mode YPOS
	WriteTW88( 0x10, 0x23 );			// adc start with mode YPOS
	while (( ReadTW88( 0x10 ) & 8 ) != 8 ) ;  			// wait until ADC
	WriteTW88( 0x10, 0x0b );			// adc start with mode YPOS
	WriteTW88( 0x10, 0x23 );			// adc start with mode YPOS
	while (( ReadTW88( 0x10 ) & 8 ) != 8 ) ;  			// wait until ADC
	WriteTW88( 0x10, 0x0b );			// adc start with mode YPOS
	WriteTW88( 0x10, 0x23 );			// adc start with mode YPOS
	while (( ReadTW88( 0x10 ) & 8 ) != 8 ) ;  			// wait until ADC

	v = ReadTW88( 0x12 );
	v <<= 4;
	v += ReadTW88( 0x13 );
	return v;
}

BYTE GetZPS(void)
{
	BYTE	z1, z2;

	WriteTW88( 0x10, 0x09 );				// write Start, erase Ready, mode Z1 for touch
	WriteTW88( 0x10, 0x21 );				// write Start, erase Ready, mode Z1 for touch
	while (( ReadTW88( 0x10 ) & 8 ) != 8 ) ;
	WriteTW88( 0x10, 0x09 );				// write Start, erase Ready, mode Z1 for touch
	WriteTW88( 0x10, 0x21 );				// write Start, erase Ready, mode Z1 for touch
	while (( ReadTW88( 0x10 ) & 8 ) != 8 ) ;
	WriteTW88( 0x10, 0x09 );				// write Start, erase Ready, mode Z1 for touch
	WriteTW88( 0x10, 0x21 );				// write Start, erase Ready, mode Z1 for touch
	while (( ReadTW88( 0x10 ) & 8 ) != 8 ) ;
	z1 = ReadTW88( 0x12 ); 
	if ( z1 == 0 ) return (255);
	//z1 <<= 4;
	//z1 += ReadTW88( 0x13 );
	WriteTW88( 0x10, 0x0a );				// write Start, erase Ready, mode Z2 for touch
	WriteTW88( 0x10, 0x22 );				// write Start, erase Ready, mode Z2 for touch
	while (( ReadTW88( 0x10 ) & 8 ) != 8 ) ;
	WriteTW88( 0x10, 0x0a );				// write Start, erase Ready, mode Z2 for touch
	WriteTW88( 0x10, 0x22 );				// write Start, erase Ready, mode Z2 for touch
	while (( ReadTW88( 0x10 ) & 8 ) != 8 ) ;
	WriteTW88( 0x10, 0x0a );				// write Start, erase Ready, mode Z2 for touch
	WriteTW88( 0x10, 0x22 );				// write Start, erase Ready, mode Z2 for touch
	while (( ReadTW88( 0x10 ) & 8 ) != 8 ) ;
	z2 = ReadTW88( 0x12 ); 

	return (z2 - z1);
}


